package com.bdqn.business.student.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bdqn.base.BaseService;
import com.bdqn.business.academic.dao.*;
import com.bdqn.business.access.dao.UserRepository;
import com.bdqn.business.quality.dao.StudentManagerMapper;
import com.bdqn.business.student.dao.AskResultMapper;
import com.bdqn.business.student.dao.SelectionResultMapper;
import com.bdqn.business.student.dao.SingleResultMapper;
import com.bdqn.business.student.dao.UpperResultMapper;
import com.bdqn.entity.academic.Exam;
import com.bdqn.entity.academic.Score;
import com.bdqn.entity.academic.Selection;
import com.bdqn.entity.academic.Single;
import com.bdqn.entity.access.User;
import com.bdqn.entity.quality.Student;
import com.bdqn.entity.student.AskResult;
import com.bdqn.entity.student.SelectionResult;
import com.bdqn.entity.student.SingleResult;
import com.bdqn.entity.student.UpperResult;
import com.bdqn.error.CommonException;
import com.bdqn.response.PageResult;
import com.bdqn.response.ProfileResult;
import com.bdqn.response.Result;
import com.bdqn.response.ResultCode;
import com.bdqn.utils.UploadUtils;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.transaction.Transactional;
import java.io.IOException;
import java.util.*;

@Service
@Transactional
@SuppressWarnings("all")
public class StudentExamService extends BaseService {


    @Autowired
    private StudentManagerMapper studentManagerMapper;

    @Autowired
    private ExamMapper examMapper;

    @Autowired
    private ScoreMapper scoreMapper;


    @Autowired
    private SingleMapper singleMapper;

    @Autowired
    private SelectionMapper selectionMapper;

    @Autowired
    private AskMapper askMapper;

    @Autowired
    private UpperMapper upperMapper;

    @Autowired
    private FastFileStorageClient fastFileStorageClient;

    @Autowired
    private SingleResultMapper singleResultMapper;

    @Autowired
    private SelectionResultMapper selectionResultMapper;

    @Autowired
    private AskResultMapper askResultMapper;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private UpperResultMapper upperResultMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public Result getList(Map<String, Object> map) {


        Integer page = Integer.parseInt(map.get("page").toString());
        Integer size = Integer.parseInt(map.get("size").toString());



        ProfileResult profileResult = (ProfileResult) SecurityUtils.getSubject().getPrincipal();
        String id = profileResult.getId();


        /*User user = userRepository.findById(id).get();

        if(!"2".equals(user.getType())){
            return new Result(ResultCode.FAIL);
        }
*/


        //根据当前用户的id来查询所在班级
        Student student = studentManagerMapper.selectById(id);




        String classesId = student.getClassesId();

        //说明该用户还没有班级
        if(classesId == null) return Result.FAIL();


        QueryWrapper<Exam> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("classes_id",classesId);

        queryWrapper.orderByDesc("create_time");

        IPage<Exam> iPage = new Page<>(page,size);

        IPage<Exam> result = examMapper.selectPage(iPage, queryWrapper);

        PageResult<Exam> pageResult = new PageResult<>(result.getTotal(),result.getRecords());

        return new Result(ResultCode.SUCCESS,pageResult);

    }


    public Result getScoreStatus(String id) throws CommonException {

        //查看试卷状态,如果试卷状态不是2,则说明用户通过非法途径进入,则拒绝
        Exam exam = examMapper.selectById(id);
        String examStatus = exam.getExamStatus();
        if(!"2".equals(examStatus)) return new Result(ResultCode.EXAM_NO_START);

        //查询当前试卷 当前学生的score成绩单中的status 0 为初始化 1未交卷  2已交卷
        ProfileResult profileResult = (ProfileResult) SecurityUtils.getSubject().getPrincipal();
        String studentId = profileResult.getId();
        QueryWrapper<Score> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("student_id",studentId);
        queryWrapper.eq("exam_id",id);

        Score score = scoreMapper.selectOne(queryWrapper);

        if(score != null && score.getStatus() != null){
            String status = score.getStatus();

            if("0".equals(status)){
                score.setStatus("1");
                score.setModifyId(currentUser().getId());
                score.setModifyUser(currentUser().getNickName());
                score.setModifyTime(new Date());
                scoreMapper.updateById(score);
            }

            if("2".equals(status)) throw new CommonException(ResultCode.EXAM_IS_COMMIT);

            return Result.SUCCESS();
        }

        throw new CommonException(ResultCode.FAIL);
    }

    public Result findExamByRedis(String id) {
        Object exam = redisTemplate.opsForValue().get("exam" + id);
        Map<String, Object> map = JSON.parseObject(exam.toString(), Map.class);
        return new Result(ResultCode.SUCCESS,map);
    }

    public Result saveTempDataToRedis(Map<String, Object> map) {
        String examId = map.get("id").toString();
        Exam exam = examMapper.selectById(examId);

        //如果不等于2 说明已经停止答题 那么前台学生端需要强制交卷
        if(!"2".equals(exam.getExamStatus())){
            return Result.FAIL();
        }else{//否则的话 需要把学生的答题数据临时保存到缓存中
            String singleOptions = map.get("singleOptions").toString();
            String selectionOptions = map.get("selectionOptions").toString();
            String askOptions = map.get("askOptions").toString();

            String studentId = currentUser().getId();

            StringBuffer sb = new StringBuffer();
            //1,2,3#1,2,3@1,2,3@5#大健康大石街道看!&kls;dkl
            sb.append(singleOptions).append("#").append(selectionOptions).append("#").append(askOptions);

            Object temp = redisTemplate.opsForValue().get("temp_exam::" + examId + "::" + studentId);

            if(temp != null){ //说明有redis中有数据，则先删除后新增
                redisTemplate.delete("temp_exam::" + examId + "::" + studentId);
            }
            //说明没有数据则新增
            redisTemplate.opsForValue().set("temp_exam::" + examId + "::" + studentId,sb.toString().trim());
            return Result.SUCCESS();

        }
    }

    public Result echoTempAnswer(String examId) {
        String studentId = currentUser().getId();
        String answer = "";
        Object temp = redisTemplate.opsForValue().get("temp_exam::" + examId + "::" + studentId);
        if(temp != null){
            answer = temp.toString();
        }
        return new Result(ResultCode.SUCCESS,answer);
    }


    //非常关键的方法:  自动判分(单选,多选题)
    public Result saveStudentExam(Map<String, Object> map) {
        String questionTypeIds = map.get("questionTypeIds").toString();
        String examId = map.get("id").toString();
        String studentId = currentUser().getId();

        Exam exam = examMapper.selectById(examId);

        QueryWrapper<Score> scoreQueryWrapper = new QueryWrapper<>();
        scoreQueryWrapper.eq("exam_id",examId);
        scoreQueryWrapper.eq("student_id",studentId);
        Score score = scoreMapper.selectOne(scoreQueryWrapper);

        Integer totalScore = 0;

        //单选题自动判分
        if(questionTypeIds.contains("1")){
            //获得前台传递过来的学生答案集合
            List<String> singleOptions = (List<String>) map.get("singleOptions");

            //String singleSuccIds = "";
            List<String>singleSuccIds = new ArrayList<>();


            //String singleErrIds = "";
            List<String>singleErrIds = new ArrayList<>();
            Integer singleSucc = 0;
            Integer singleErr = 0;
            Integer singleScore = 0;


            String[] singleIdArray = exam.getSingleJoins().split(",");// 单选题的id组  ==> 拿到单选题 ==> 单选的真正答案
            Integer oneSingleScore = exam.getSingleScore();  //单选题的每题分数

            for (int i = 0; i < singleIdArray.length; i ++) {
                Single single = singleMapper.selectById(singleIdArray[i]);
                String singleAsk = single.getSingleAsk();
                //真正的答案与学生的答案进行对比(一道题的)
                if(singleAsk.equals(singleOptions.get(i))){
                    singleSuccIds.add(singleIdArray[i]);
                    //singleSuccIds += "," + singleIdArray[i] ; //如果进入这个if 则说明答对了  拼接score表中 singleSucc 字段的值
                    singleSucc += 1; //答对题数+1
                    singleScore += oneSingleScore; //单选总分=  单选题每题分数 + 单选题总分
                    totalScore += oneSingleScore;  //总成绩 = 总成绩 + 单选题每题分数
                }else{
                    //singleErrIds += "," + singleIdArray[i];//拼接score表中 singleErr 字段的值
                    singleErrIds.add(singleIdArray[i]);
                    singleErr += 1; //错题数 + 1
                }

                //处理st_single_result表  ---> 扩展操作: 为了最终回显
                SingleResult singleResult = SingleResult.builder()
                        .singleId(singleIdArray[i])
                        .optionIds(singleOptions.get(i))
                        .studentId(studentId)
                        .examId(examId)
                        .build();
                singleResultMapper.insert(singleResult);
            }

            score.setSingleErr(singleErr);
            score.setSingleErrIds(StringUtils.join(singleErrIds,","));

            score.setSingleSucc(singleSucc);
            score.setSingleSuccIds(StringUtils.join(singleSuccIds,","));

            score.setSingleScore(singleScore);
        }

        if(questionTypeIds.contains("2")){
            String[] selectionOptions = map.get("selectionOptions").toString().split("@");

            //String selectionSuccIds = "";
            List<String>selectionSuccIds = new ArrayList<>();
            //String selectionErrIds = "";
            List<String>selectionErrIds = new ArrayList<>();
            Integer selectionSucc = 0;
            Integer selectionErr = 0;
            Integer selectionScore = 0;

            String[] selectionIdArray = exam.getSelectionJoins().split(",");
            Integer oneSelectionScore = exam.getSelectionScore();

            for(int i = 0 ; i < selectionIdArray.length; i++){
                Selection selection = selectionMapper.selectById(selectionIdArray[i]);
                String selectionAsk = this.sort(selection.getSelectionAsk());
                String strings = selectionOptions[i];
                String studentSelectionAsk = this.sort(strings);
                if(selectionAsk.equals(studentSelectionAsk)){
                    //selectionSuccIds += "," + selectionIdArray[i];
                    selectionSuccIds.add(selectionIdArray[i]);
                    selectionSucc += 1;
                    selectionScore += oneSelectionScore;
                    totalScore += oneSelectionScore;
                }else{
                    //selectionErrIds += "," + selectionIdArray[i];
                    selectionErrIds.add(selectionIdArray[i]);
                    selectionErr += 1;
                }

                //处理st_selection_result表
                SelectionResult selectionResult = SelectionResult.builder()
                        .selectionId(selectionIdArray[i])
                        .examId(exam.getId())
                        .optionIds(studentSelectionAsk)
                        .studentId(studentId)
                        .build();

                selectionResultMapper.insert(selectionResult);
            }

            score.setSelectionErr(selectionErr);
            score.setSelectionErrIds(StringUtils.join(selectionErrIds,","));

            score.setSelectionSucc(selectionSucc);
            score.setSelectionSuccIds(StringUtils.join(selectionSuccIds,","));

            score.setSelectionScore(selectionScore);

        }

        //因为在开始的时候就已经初始化学生的问答题了, 所以在这里是需要修改的
        if(questionTypeIds.contains("3")){
            List<String> askOptions = (List<String>) map.get("askOptions");
            String[] askIdArray = exam.getAskJoins().split(",");
            for(int i = 0; i < askIdArray.length ; i ++){
                QueryWrapper<AskResult> askResultQueryWrapper = new QueryWrapper<>();
                askResultQueryWrapper.eq("ask_id",askIdArray[i]);
                askResultQueryWrapper.eq("exam_id",exam.getId());
                askResultQueryWrapper.eq("student_id",studentId);
                AskResult askResult = askResultMapper.selectOne(askResultQueryWrapper);
                askResult.setAskAnswer(askOptions.get(i));
                askResultMapper.updateById(askResult);
            }
        }


        if("1".equals(score.getStatus())){  //屏蔽为0的学生
            score.setStatus("2");
        }

        score.setScore(totalScore);
        score.setExecuteTime(new Date());
        scoreMapper.updateById(score);

        return Result.SUCCESS();

    }

    protected static String sort(String options){
        if(!"".equals(options)){
            String[] split = options.split(",");
            Integer [] target = new Integer[split.length];
            for (int i = 0; i < split.length; i++) {
                target[i] = Integer.parseInt(split[i]);
            }
            Arrays.sort(target);
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < target.length; i++) {
                sb.append(",").append(target[i]);
            }
            String substring = sb.toString().substring(1);
            return substring;
        }
        return "";
    }

    public Result uploadStudentUpper(MultipartFile file,Map<String,Object> map) throws IOException {


        String examId = map.get("examId").toString();

        Exam exam = examMapper.selectById(examId);

        if(exam.getQuestionTypeIds().contains("4")){
            ProfileResult profileResult = (ProfileResult) SecurityUtils.getSubject().getPrincipal();
            String id = profileResult.getId();

            String uploadFile = UploadUtils.createUploadFile(fastFileStorageClient, file);
            String url = "http://47.97.77.138:8888/" + uploadFile;


            QueryWrapper<UpperResult> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("exam_id",examId);
            queryWrapper.eq("student_id",id);
            UpperResult upperResult = upperResultMapper.selectOne(queryWrapper);

            if(upperResult != null){
                upperResult.setUrl(url);
                upperResultMapper.updateById(upperResult);
            }else{
                UpperResult target = new UpperResult();
                target.setStudentId(id);
                target.setUrl(url);
                target.setScore(0);
                target.setMarkingStatus("1");
                target.setExamId(examId);
                upperResultMapper.insert(target);
            }

            return Result.SUCCESS();
        }else{
            return Result.FAIL();
        }
    }

    public Result checkUpperResult(String examId) {
        ProfileResult profileResult = (ProfileResult) SecurityUtils.getSubject().getPrincipal();
        String studentId = profileResult.getId();
        QueryWrapper<UpperResult> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("student_id",studentId);
        queryWrapper.eq("exam_id",examId);
        UpperResult upperResult = upperResultMapper.selectOne(queryWrapper);
        if(upperResult.getUrl() == null){
            return Result.SUCCESS();
        }else{
            return Result.FAIL();
        }
    }

    public Result getShowExamStatus(String id) {

        String studentId = currentUser().getId();

        QueryWrapper<Score> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("student_id",studentId);
        queryWrapper.eq("exam_id",id);

        Score score = scoreMapper.selectOne(queryWrapper);

        Exam exam = examMapper.selectById(id);

        if("6".equals(exam.getExamStatus())){
            return Result.SUCCESS();
        }else{
            return Result.FAIL();
        }
    }


    public Result goBackStudentExamData(Exam exam) {

        String studentId = currentUser().getId();

        String questionTypeIds = exam.getQuestionTypeIds();

        Map<String,Object> returnMap = new HashMap<>();

        if(questionTypeIds.contains("1")){
            String singleJoins = exam.getSingleJoins();
            String[] singleIdArray = singleJoins.split(",");

            List<SingleResult> list = new ArrayList<>();

            for (String singleId : singleIdArray) {
                QueryWrapper<SingleResult> queryWrapper = new QueryWrapper();
                queryWrapper.eq("single_id",singleId);
                queryWrapper.eq("exam_id",exam.getId());
                queryWrapper.eq("student_id",studentId );

                List<SingleResult> singleResults = singleResultMapper.selectList(queryWrapper);
                if(!CollectionUtils.isEmpty(singleResults) && singleResults.size() > 0) list.add(singleResults.get(0));
            }

            returnMap.put("singleResults",list);
        }

        if(questionTypeIds.contains("2")){
            String selectionJoins = exam.getSelectionJoins();
            String[] selectionIdArray = selectionJoins.split(",");

            List<SelectionResult> list = new ArrayList<>();

            for (String selectionId : selectionIdArray) {
                QueryWrapper<SelectionResult> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("exam_id",exam.getId());
                queryWrapper.eq("student_id",studentId);
                queryWrapper.eq("selection_id",selectionId);

                SelectionResult selectionResult = selectionResultMapper.selectOne(queryWrapper);

                list.add(selectionResult);

            }

            returnMap.put("selectionResults",list);

        }

        if(questionTypeIds.contains("3")){
            String askJoins = exam.getAskJoins();

            String[] askIdArray = askJoins.split(",");

            List<AskResult> list = new ArrayList<>();



            for (String askId : askIdArray) {
                QueryWrapper<AskResult> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("ask_id",askId);
                queryWrapper.eq("exam_id",exam.getId());
                queryWrapper.eq("student_id",studentId);

                List<AskResult> askResults = askResultMapper.selectList(queryWrapper);

                if(!CollectionUtils.isEmpty(askResults) && askResults.size() > 0) list.add(askResults.get(0));
            }

            returnMap.put("askResults",list);
        }



        QueryWrapper<Score> scoreQueryWrapper = new QueryWrapper<>();
        scoreQueryWrapper.eq("student_id",studentId);
        scoreQueryWrapper.eq("exam_id",exam.getId());


        Score score = scoreMapper.selectOne(scoreQueryWrapper);

        returnMap.put("score",score);

        return new Result(ResultCode.SUCCESS,returnMap);
    }


    public Result getExamTypeAndStudentScore(String id) {
        Exam exam = examMapper.selectById(id);

        QueryWrapper<Score> scoreQueryWrapper = new QueryWrapper<>();
        scoreQueryWrapper.eq("student_id",currentUser().getId());
        scoreQueryWrapper.eq("exam_id",id);
        Score score = scoreMapper.selectOne(scoreQueryWrapper);

        if(("4".equals(exam.getExamStatus()) || "5".equals(exam.getExamStatus()) ) && "0".equals(score.getStatus())){
            return Result.SUCCESS();
        }


        return Result.FAIL();
    }

    public Result updateScoreStatus(String id) {
        Exam exam = examMapper.selectById(id);

        QueryWrapper<Score> scoreQueryWrapper = new QueryWrapper<>();
        scoreQueryWrapper.eq("student_id",currentUser().getId());
        scoreQueryWrapper.eq("exam_id",id);
        Score score = scoreMapper.selectOne(scoreQueryWrapper);

        score.setStatus("1");

        scoreMapper.updateById(score);

        return Result.SUCCESS();
    }

}
